Матр.отд
Главная     ◄Глагол     ◄Азбука     ◄Задачи на Глаголе     Примеры приложений ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы
 
 glagol.png Программируем по-русски
 

Основная задача Глагола — дать человеку возможность воплощать свои мысли на языке, близком к его родному языку.

Издатель Глагола
 

 

(******************************************************************************)
(**)                        ОТДЕЛ Матр;
(******************************************************************************
 * НАЗНАЧЕНИЕ: определение матриц и основные вычисления над ними
 *
 * Источники, ссылки, библиография
   Debord J., Библиотека математических подпрограмм
   tpmath.zip

   Goffe B., Программа SimAnn.FOR (Simulated Annealing in Fortran)
   http://www.netlib.org/opt/simann.f

   EISPACK: Библиотека Фортран функций для вычисления собственных значений и векторов
   http://www.netlib.org/eispack

   Marsaglia G., Тесты для генераторов случайных чисел
   http://stat.fsu.edu/~geo/diehard.html

   Moshier S., Библиотека математических подпрограмм
   http://www.moshier.net

   Press W.H., Teukolsky S.A., Vetterling W.T., Flannery B.P.
   Численные рецепты на Паскале
   http://garbo.uwasa.fi/pc/turbopas.html

   Пакет численных методов для Турбо Паскаля
   Borland International, 1986
 *
 ******************************************************************************)
ИСПОЛЬЗУЕТ Матем,Вект;

ВИД 
  Вещ = Матем.Вещ;            

(******************************************************************************
 * Код ошибки после выполнения функций
 ******************************************************************************)
ПОСТ
  ВЫРОЖДЕНА-     =-1;  (* вырожденная матрица *)
  НЕТ_СХОДИМОСТИ-=-2;  (* нет сходимости *)
  НЕ_П_О-        =-3;  (* матрица не является положительно определённой *)

ВИД
  Вид-=РЯД ИЗ Вект.Вид;
  Доступ-=ДОСТУП К Вид;

  Перестановки-=ДОСТУП К РЯД ИЗ ЦЕЛ;
  
(******************************************************************************
 * Переписывание матриц и векторов
 ******************************************************************************)
                                                     (* заготовки ЗАДАЧ *)
ЗАДАЧА^ ОбменСтрок-(A+:Вид; i,k:ЦЕЛ);
ЗАДАЧА^ ОбменСтолбцов-(A+:Вид; j,k:ЦЕЛ);
ЗАДАЧА^ СписатьВектор-(из-+:Вект.Вид);
ЗАДАЧА^ Списать-(из-+:Вид);
ЗАДАЧА^ СписатьСтолбецИзВектора-(из-:Вект.Вид; в+:Вид; стлб:ЦЕЛ);
ЗАДАЧА^ СписатьВекторИзСтолбеца-(из-:Вид; в+:Вект.Вид; стлб:ЦЕЛ);

(******************************************************************************)
ЗАДАЧА^ МетодГаусса-(A-:Вид; b-:Вект.Вид; Ao+:Вид; x+:Вект.Вид):ЦЕЛ;
(* Цель:  решение системы линейных алгебраических уравнений методом
 *        исключения Гаусса
 ******************************************************************************
 * До:    < A >  - матрица системы
 *        < b >  - вектор свободных членов
 * После: < Ao > - обратная матрица
 *        < x >  - вектор решения
 * Ответ: 0 или ВЫРОЖДЕНА *)

(******************************************************************************)
ЗАДАЧА^ Обратить-(A-,Ao+:Вид):ЦЕЛ;
(* Цель:  обращение квадратной матрицы методом Гаусса
 ******************************************************************************
 * До:    < A >  - исходная матрица
 * После: < Ao > - обратная матрица
 * Ответ: 0 или ВЫРОЖДЕНА *)

(******************************************************************************)
ЗАДАЧА^ Определитель-(A+:Вид):Вещ;
(* Цель:  вычисление определителя квадратной матрицы
 ******************************************************************************
 * До:    < A > - исходная матрица
 * После: < A > - разрушенная матрица
 * Ответ: значение определителя *)

(******************************************************************************)
ЗАДАЧА^ РазложитьНаLL-(A-,L+:Вид):ЦЕЛ;
(* Цель:  Разложение Холецкого (A=L*L') симметрической положительно
 *        определенной матрицы A на две треугольные матрицы L и L', где L - это
 *        нижняя треугольная матрица, а L' - матрица, транспонированная к L.
 ******************************************************************************
 * Прим:  Эту задачу можно использовать для испытания на положительно
 *        определенность.
 * До:    < A >    - исходная матрица A
 * После: < L >    - матрица L
 * Ответ: 0 или НЕ_П_О *)

(******************************************************************************)
ЗАДАЧА^ РазложитьНаLU-(A+:Вид; строки+:Перестановки):ЦЕЛ;
(* Цель:  LU-разложение (A=L*U) квадратной матрицы A на два сомножителя L и U,
 *        где L - это нижняя треугольная матрица с единичной главной диагональю,
 *          а U - верхняя треугольная матрица. Эта задача используется
 *        совместно с РешитьИзLU для решения систем уравнений.
 ******************************************************************************
 * До:    < A >      - исходная матрица
 * После: < A >      - содержит элементы и L и U
 *        <строки> - вновь созданные записи о перестановках строк
 * Ответ: 0 или ВЫРОЖДЕНА *)

(******************************************************************************)
ЗАДАЧА^ РешитьИзLU-(A-:Вид; b-:Вект.Вид; строки:Перестановки; x+:Вект.Вид);
(* Цель:  решение системы уравнений после преобразования исходной матрицы
 *        с помощью РазложитьНаLU
 * До:    < A >      - матрицы L и U после РазложитьНаLU
 *        < b >      - вектор свободных членов
 *        <строки> - записи о перестановках строк из РазложитьНаLU
 * После: < x >      - вектор решения *)

(******************************************************************************)
ЗАДАЧА^ РазложитьНаSV-(A+:Вид; s+:Вект.Вид; V+:Вид):ЦЕЛ;
(* Цель:  SV разложение прямоугольной матрицы A (N x M, с N >= M) на три
 *        сомножителя (A=U*S*V'), где U (N x M) состоит из столбцов - собственных
 *        векторов, S (M x M) - диагональная матрица с элементами >= 0 (собственные
 *        значения) и V (M x M) - ортогональная матрица. Эта задача используется
 *        совместно с РешитьИзSV для решения систем уравнений.
 ******************************************************************************
 * До:    < A >      - исходная матрица
 * После: < A >      - содержит элементы U
 *        < s >      - вектор собственных значений
 *        < V >      - ортогональная матрица       
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)

(******************************************************************************)
ЗАДАЧА^ ОбнулитьS-(s+:Вект.Вид; откл:Вещ);
(* Цель:  обнуляет наименьшие собственные значения по заданной границе
 ******************************************************************************
 * До:    < s >    - вектор собственных значений S
 *        <откл> - относительное отклонение (граница будет равна откл*макс(S) )
 * После: < s >    - измененный вектор собственных значений *)

(******************************************************************************)
ЗАДАЧА^ РешитьИзSV-(U-:Вид; s-:Вект.Вид; V-:Вид; b-,x+:Вект.Вид);
(* Цель:  решение системы уравнений после преобразования исходной матрицы
 *        с помощью РазложитьНаSV и обнуления наименьших собственных значений
 *        с помощью ОбнулитьS
 ******************************************************************************
 * До:    < U > - матрица U после РазложитьНаSV
 *        < s > - вектор  S после РазложитьНаSV
 *        < V > - матрица V после РазложитьНаSV
 *        < b > - вектор свободных членов
 * После: < x > - вектор решения (V*Diag(1/S(i))*U'*B, для S(i) # 0) *)

(******************************************************************************)
ЗАДАЧА^ ВосстановитьИзSV-(U-:Вид; s-:Вект.Вид; V-,A+:Вид);
(* Цель:  восстанавливает матрицу A перемножая U, S и V' после
 *        обнуления наименьших собственных значений задачей ОбнулитьS 
 ******************************************************************************
 * До:    < U > - матрица U после РазложитьНаSV
 *        < s > - вектор  S после РазложитьНаSV
 *        < V > - матрица V после РазложитьНаSV
 * После: < A > - восстановленная матрица *)

(******************************************************************************)
ЗАДАЧА^ РазложитьНаQR-(A+,R+:Вид):ЦЕЛ;
(* Цель:  QR разложение прямоугольной матрицы  (N x M, с N >= M) на два
 *        сомножителя (A=Q*R), где Q (N x M) - ортогональная матрица, а
 *        R (M x M) - верхняя треугольная матрица. Эта задача используется
 *        совместно с РешитьИзQR для решения систем уравнений.
 ******************************************************************************
 * До:    < A > - исходная матрица
 * После: < A > - содержит элементы Q
 *        < R > - верхняя треугольная матрица
 * Ответ: 0 или ВЫРОЖДЕНА *)

(******************************************************************************)
ЗАДАЧА^ РешитьИзQR-(q-,R-:Вид; b-,x+:Вект.Вид);
(* Цель:  решение системы уравнений после преобразования исходной матрицы
 *        с помощью РазложитьНаQR
 ******************************************************************************
 * До:    < q > - матрица Q после РазложитьНаQR
 *        < R > - матрица R после РазложитьНаQR
 *        < b > - вектор свободных членов
 * После:  - вектор решения *)
                                              (* полные реализации ЗАДАЧ *)
(******************************************************************************)
ЗАДАЧА ОбменСтрок-(A+:Вид; i,k:ЦЕЛ);
ПЕР
  j:ЦЕЛ;
УКАЗ
  ОТ j:=0 ДО РАЗМЕР(A,1)-1 ВЫП
    Матем.обмен(A[i,j],A[k,j]) 
  КОН
КОН ОбменСтрок;

(******************************************************************************)
ЗАДАЧА ОбменСтолбцов-(A+:Вид; j,k:ЦЕЛ);
ПЕР
  i:ЦЕЛ;
УКАЗ
  ОТ i:=0 ДО РАЗМЕР(A,0)-1 ВЫП
    Матем.обмен(A[i,j],A[i,k])
  КОН
КОН ОбменСтолбцов;

(******************************************************************************)
ЗАДАЧА СписатьВектор-(из-+:Вект.Вид);
ПЕР
  i:ЦЕЛ;
УКАЗ
  ОТ i:=0 ДО РАЗМЕР(из)-1 ВЫП
    в[i]:=из[i]
  КОН
КОН СписатьВектор;

(******************************************************************************)
ЗАДАЧА Списать-(из-+:Вид);
ПЕР
  i,j:ЦЕЛ;
УКАЗ
  ОТ i:=0 ДО Матем.минЦ(РАЗМЕР(из,0),РАЗМЕР(в,0))-1 ВЫП
    ОТ j:=0 ДО Матем.минЦ(РАЗМЕР(из,1),РАЗМЕР(в,1))-1 ВЫП
      в[i,j]:=из[i,j] 
    КОН 
  КОН
КОН Списать;

(******************************************************************************)
ЗАДАЧА СписатьСтолбецИзВектора-(из-:Вект.Вид; в+:Вид; стлб:ЦЕЛ);
ПЕР
  i:ЦЕЛ;
УКАЗ
  ОТ i:=0 ДО Матем.минЦ(РАЗМЕР(из),РАЗМЕР(в,0))-1 ВЫП
    в[i,стлб]:=из[i]
  КОН
КОН СписатьСтолбецИзВектора;

(******************************************************************************)
ЗАДАЧА СписатьВекторИзСтолбеца-(из-:Вид; в+:Вект.Вид; стлб:ЦЕЛ);
ПЕР
  i:ЦЕЛ;
УКАЗ
  ОТ i:=0 ДО Матем.минЦ(РАЗМЕР(из),РАЗМЕР(в,0))-1 ВЫП
    в[i]:=из[i,стлб]
  КОН
КОН СписатьВекторИзСтолбеца;

(******************************************************************************)
ЗАДАЧА МетодГаусса-(A-:Вид; b-:Вект.Вид; Ao+:Вид; x+:Вект.Вид):ЦЕЛ;
(* Цель:  решение системы линейных алгебраических уравнений методом
 *        исключения Гаусса
 ******************************************************************************
 * До:    < A >  - матрица системы
 *        < b >  - вектор свободных членов
 * После: < Ao > - обратная матрица
 *        < x >  - вектор решения
 * Ответ: 0 или ВЫРОЖДЕНА *)
ПЕР
  i,j,k,посл:ЦЕЛ;
  вед,t:Вещ;
  ведСтр,ведСтлб:ДОСТУП К РЯД ИЗ ЦЕЛ; (* строки и столбцы ведущего элемента *)
УКАЗ
  посл:=РАЗМЕР(A)-1;
  СОЗДАТЬ(ведСтр,посл+1);
  СОЗДАТЬ(ведСтлб,посл+1);
  Списать(A,Ao);
  СписатьВектор(b,x);

  ОТ k:=0 ДО посл ВЫП
      (* поиск наибольшего ведущего элемента в подматрице Ao[k..посл,k..посл] *)
    вед:=Ao[k,k];
    ведСтр[k]:=k;
    ведСтлб[k]:=k;
    ОТ i:=k ДО посл ВЫП
      ОТ j:=k ДО посл ВЫП
        ЕСЛИ МОДУЛЬ(Ao[i,j]) > МОДУЛЬ(вед) ТО
          вед:=Ao[i,j];
          ведСтр[k]:=i;
          ведСтлб[k]:=j
        КОН 
      КОН 
    КОН;
             (* ведущий элемент слабоват => псевдо-вырожденная матрица *)
    ЕСЛИ МОДУЛЬ(вед) < Матем.МАШЕПС ТО
      ВОЗВРАТ ВЫРОЖДЕНА
    КОН;
              (* обмен текущей строки (k) со строкой ведущего элемента *)
    ЕСЛИ ведСтр[k] # k ТО
      ОбменСтрок(Ao,ведСтр[k],k);
      Матем.обмен(x[ведСтр[k]],x[k])
    КОН;
           (* обмен текущего столбца (k) со столбцом ведущего элемента *)
    ЕСЛИ ведСтлб[k] # k ТО
      ОбменСтолбцов(Ao,ведСтлб[k],k) 
    КОН;
             (* преобразование строки ведущего элемента *)
    Ao[k,k]:=1;
    ОТ j:=0 ДО посл ВЫП
      Ao[k,j]:=Ao[k,j]/вед 
    КОН;
    x[k]:=x[k]/вед;
             (* преобразование оставшихся строк *)
    ОТ i:=0 ДО посл ВЫП
      ЕСЛИ i # k ТО
        t:=Ao[i,k];
        Ao[i,k]:=0;
        ОТ j:=0 ДО посл ВЫП
          Ao[i,j]:=Ao[i,j]-t*Ao[k,j]
        КОН;
        x[i]:=x[i]-t*x[k]
      КОН 
    КОН
  КОН;
             (* перестановка обратной матрицы *)
  ОТ i:=посл ДО 0 ПО -1 ВЫП
    ЕСЛИ ведСтлб[i] # i ТО
      ОбменСтрок(Ao,ведСтлб[i],i);
      Матем.обмен(x[ведСтлб[i]],x[i])
    КОН 
  КОН;
  ОТ j:=посл ДО 0 ПО -1 ВЫП
    ЕСЛИ ведСтр[j] # j ТО
      ОбменСтолбцов(Ao,ведСтр[j],j) 
    КОН 
  КОН;

  ВОЗВРАТ 0
КОН МетодГаусса;

(******************************************************************************)
ЗАДАЧА Обратить-(A-:Вид; Ao+:Вид):ЦЕЛ;
(* Цель:  обращение квадратной матрицы методом Гаусса
 ******************************************************************************
 * До:    < A >  - исходная матрица
 * После: < Ao > - обратная матрица
 * Ответ: 0 или ВЫРОЖДЕНА *)
ПЕР
  i,j,k,посл:ЦЕЛ;
  вед,t:Вещ;
  ведСтр,ведСтлб:ДОСТУП К РЯД ИЗ ЦЕЛ; (* строки и столбцы ведущего элемента *)
УКАЗ
  посл:=РАЗМЕР(A)-1;
  СОЗДАТЬ(ведСтр,посл+1);
  СОЗДАТЬ(ведСтлб,посл+1);
  Списать(A,Ao);

  ОТ k:=0 ДО посл ВЫП
      (* поиск наибольшего ведущего элемента в подматрице Ao[k..посл,k..посл] *)
    вед:=Ao[k,k];
    ведСтр[k]:=k;
    ведСтлб[k]:=k;
    ОТ i:=k ДО посл ВЫП
      ОТ j:=k ДО посл ВЫП
        ЕСЛИ МОДУЛЬ(Ao[i,j]) > МОДУЛЬ(вед) ТО
          вед:=Ao[i,j];
          ведСтр[k]:=i;
          ведСтлб[k]:=j
        КОН 
      КОН 
    КОН;
             (* ведущий элемент слабоват => псевдо-вырожденная матрица *)
    ЕСЛИ МОДУЛЬ(вед) < Матем.МАШЕПС ТО
      ВОЗВРАТ ВЫРОЖДЕНА
    КОН;
              (* обмен текущей строки (k) со строкой ведущего элемента *)
    ЕСЛИ ведСтр[k] # k ТО
      ОбменСтрок(Ao,ведСтр[k],k) 
    КОН;
           (* обмен текущего столбца (k) со столбцом ведущего элемента *)
    ЕСЛИ ведСтлб[k] # k ТО
      ОбменСтолбцов(Ao,ведСтлб[k],k) 
    КОН;
             (* преобразование строки ведущего элемента *)
    Ao[k,k]:=1;
    ОТ j:=0 ДО посл ВЫП
      Ao[k,j]:=Ao[k,j]/вед 
    КОН;
             (* преобразование оставшихся строк *)
    ОТ i:=0 ДО посл ВЫП
      ЕСЛИ i # k ТО
        t:=Ao[i,k];
        Ao[i,k]:=0;
        ОТ j:=0 ДО посл ВЫП
          Ao[i,j]:=Ao[i,j]-t*Ao[k,j]
        КОН
      КОН 
    КОН
  КОН;
             (* перестановка обратной матрицы *)
  ОТ i:=посл ДО 0 ПО -1 ВЫП
    ЕСЛИ ведСтлб[i] # i ТО
      ОбменСтрок(Ao,ведСтлб[i],i) 
    КОН 
  КОН;
  ОТ j:=посл ДО 0 ПО -1 ВЫП
    ЕСЛИ ведСтр[j] # j ТО
      ОбменСтолбцов(Ao,ведСтр[j],j) 
    КОН 
  КОН;

  ВОЗВРАТ 0
КОН Обратить;

(******************************************************************************)
ЗАДАЧА Определитель-(A+:Вид):Вещ;
(* Цель:  вычисление определителя квадратной матрицы
 ******************************************************************************
 * До:    < A > - исходная матрица
 * После: < A > - разрушенная матрица
 * Ответ: значение определителя *)
ПЕР
  d,t:Вещ;     (* частичный определитель и множитель *)
  i,j,k,посл:ЦЕЛ;   
  опред0:КЛЮЧ; (* если определитель = 0 *)
УКАЗ
  посл:=РАЗМЕР(A)-1;
  опред0:=ОТКЛ;
  d:=1;
        (* строим верхнюю треугольную матрицу *)
  k:=0;
  ПОКА НЕ опред0 И (k < посл) ВЫП
    (* при 0-м диагональном элементе переставляем строки *)
    ЕСЛИ МОДУЛЬ(A[k,k]) < Матем.МАШЕПС ТО
      опред0:=ВКЛ;
      (* пытаемся найти строку с не 0-м элементом в этом столбце *)
      i:=k;
      ПОКА опред0 И (i < посл) ВЫП
        УВЕЛИЧИТЬ(i);
        ЕСЛИ МОДУЛЬ(A[i,k]) > Матем.МАШЕПС ТО
          (* переставляем эти две строки *)
          ОбменСтрок(A,i,k);
          опред0:=ОТКЛ;
          (* соответственно меняем знак определителя *)
          d:=-d
        КОН
      КОН
    КОН;

    ЕСЛИ НЕ опред0 ТО
      ОТ i:=k+1 ДО посл ВЫП
        ЕСЛИ МОДУЛЬ(A[i,k]) > Матем.МАШЕПС ТО
          (* обнуляем k элемент этого ряда *)
          t:=-A[i,k]/A[k,k];
          ОТ j:=1 ДО посл ВЫП
            A[i,j]:=A[i,j]+t*A[k,j]
          КОН
        КОН 
      КОН 
    КОН;

    d:=d*A[k,k]; 
    УВЕЛИЧИТЬ(k)
  КОН;

  ЕСЛИ опред0 ТО
    ВОЗВРАТ 0
  КОН;
  ВОЗВРАТ d*A[посл,посл]
КОН Определитель;

(******************************************************************************)
ЗАДАЧА РазложитьНаLL-(A-,L+:Вид):ЦЕЛ;
(* Цель:  Разложение Холецкого (A=L*L') симметрической положительно
 *        определенной матрицы A на две треугольные матрицы L и L', где L - это
 *        нижняя треугольная матрица, а L' - матрица, транспонированная к L.
 ******************************************************************************
 * Прим:  Эту задачу можно использовать для испытания на положительно
 *        определенность.
 * До:    < A >    - исходная матрица A
 * После: < L >    - матрица L
 * Ответ: 0 или НЕ_П_О *)
ПЕР
  i,j,k,посл:ЦЕЛ;
  сумма:Вещ;
УКАЗ
  посл:=РАЗМЕР(A)-1;
  ОТ k:=0 ДО посл ВЫП
    сумма:=A[k,k];
    ОТ j:=0 ДО k-1 ВЫП
      сумма:=сумма-Матем.кв(L[k,j]) 
    КОН;

    ЕСЛИ сумма <= 0 ТО
      ВОЗВРАТ НЕ_П_О
    КОН;

    L[k,k]:=Матем.квкор(сумма);
    ОТ i:=k+1 ДО посл ВЫП
      сумма:=A[i,k];
      ОТ j:=0 ДО k-1 ВЫП
        сумма:=сумма-L[i,j]*L[k,j]
      КОН;
      L[i,k]:=сумма/L[k,k]
    КОН
  КОН;
  ВОЗВРАТ 0
КОН РазложитьНаLL;

(******************************************************************************)
ЗАДАЧА РазложитьНаLU-(A+:Вид; строки+:Перестановки):ЦЕЛ;
(* Цель:  LU-разложение (A=L*U) квадратной матрицы A на два сомножителя L и U,
 *        где L - это нижняя треугольная матрица с единичной главной диагональю,
 *          а U - верхняя треугольная матрица. Эта задача используется
 *        совместно с РешитьИзLU для решения систем уравнений.
 ******************************************************************************
 * До:    < A >      - исходная матрица
 * После: < A >      - содержит элементы и L и U
 *        <строки> - вновь созданные записи о перестановках строк
 * Ответ: 0 или ВЫРОЖДЕНА *)
ПОСТ
  МАЛОЕ = 1.D-20;
ПЕР
  i,maxI,j,k,посл:ЦЕЛ;
  вед,t,сумма:Вещ;
  v:ДОСТУП К Вект.Вид;
УКАЗ
  посл:=РАЗМЕР(A)-1;
  СОЗДАТЬ(v,посл+1);
  СОЗДАТЬ(строки,посл+1);

  ОТ i:=0 ДО посл ВЫП
    вед:=0;
    ОТ j:=0 ДО посл ВЫП
      ЕСЛИ МОДУЛЬ(A[i,j]) > вед ТО
        вед:=МОДУЛЬ(A[i,j]) 
      КОН 
    КОН;
    ЕСЛИ вед < Матем.МАШЕПС ТО
      ВОЗВРАТ ВЫРОЖДЕНА
    КОН;
    v[i]:=1/вед
  КОН;
  ОТ j:=0 ДО посл ВЫП
    ОТ i:=0 ДО j-1 ВЫП
      сумма:=A[i,j];
      ОТ k:=0 ДО i-1 ВЫП
        сумма:=сумма-A[i,k]*A[k,j]
      КОН;
      A[i,j]:=сумма
    КОН;
    maxI:=0;
    вед:=0;
    ОТ i:=j ДО посл ВЫП
      сумма:=A[i,j];
      ОТ k:=0 ДО j-1 ВЫП
        сумма:=сумма-A[i,k]*A[k,j]
      КОН;
      A[i,j]:=сумма;
      t:=v[i]*МОДУЛЬ(сумма);
      ЕСЛИ t > вед ТО
        вед:=t;
        maxI:=i
      КОН
    КОН;
    ЕСЛИ j # maxI ТО
      ОбменСтрок(A,maxI,j);
      v[maxI]:=v[j]
    КОН;
    строки[j]:=maxI;
    ЕСЛИ A[j,j] = 0 ТО
      A[j,j]:=МАЛОЕ 
    КОН;
    ЕСЛИ j # посл ТО
      t:=1/A[j,j];
      ОТ i:=j+1 ДО посл ВЫП
        A[i,j]:=A[i,j]*t 
      КОН
    КОН
  КОН;
  ВОЗВРАТ 0
КОН РазложитьНаLU;

(******************************************************************************)
ЗАДАЧА РешитьИзLU-(A-:Вид; b-:Вект.Вид; строки:Перестановки; x+:Вект.Вид);
(* Цель:  решение системы уравнений после преобразования исходной матрицы
 *        с помощью РазложитьНаLU
 ******************************************************************************
 * До:    < A >    - матрица после РазложитьНаLU
 *        < b >    - вектор свободных членов
 *        <строки> - записи о перестановках строк из РазложитьНаLU
 * После: < x >    - вектор решения *)
ПЕР
  i,Ip,j,k,посл:ЦЕЛ;
  сумма:Вещ;
УКАЗ
  посл:=РАЗМЕР(A)-1;
  k:=-1;
  СписатьВектор(b,x);
  ОТ i:=0 ДО посл ВЫП
    Ip:=строки[i];
    сумма:=x[Ip];
    x[Ip]:=x[i];
    ЕСЛИ k >= 0 ТО
      ОТ j:=k ДО i-1 ВЫП
        сумма:=сумма-A[i,j]*x[j]
      КОН 
    ИНАЧЕ 
      ЕСЛИ сумма # 0 ТО
        k:=i 
      КОН 
    КОН;
    x[i]:=сумма
  КОН;
  ОТ i:=посл ДО 0 ПО -1 ВЫП
    сумма:=x[i];
    ЕСЛИ i < посл ТО
      ОТ j:=i+1 ДО посл ВЫП
        сумма:=сумма-A[i,j]*x[j]
      КОН 
    КОН;
    x[i]:=сумма/A[i,i]
  КОН
КОН РешитьИзLU;

(******************************************************************************)
ЗАДАЧА РазложитьНаSV-(A+:Вид; s+:Вект.Вид; V+:Вид):ЦЕЛ;
(* Цель:  SV разложение прямоугольной матрицы A (N x M, с N >= M) на три
 *        сомножителя (A=U*S*V'), где U (N x M) состоит из столбцов - собственных
 *        векторов, S (M x M) - диагональная матрица с элементами >= 0 (собственные
 *        значения) и V (M x M) ортогональная матрица. Эта задача используется
 *        совместно с РешитьИзSV для решения систем уравнений;
 ******************************************************************************
 * Прим:  текст этой задачи переписан из подпрограммы SVD пакета EISPACK
 * До:    < A >      - исходная матрица
 * После: < A >      - содержит элементы U
 *        < s >      - вектор собственных значений
 *        < V >      - ортогональная матрица       
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)
ПЕР
  i,Its,j,i1,k,l,n,посл1,посл2:ЦЕЛ;
  Anorm,c,f,g,h,Scale,t,x,y,z:Вещ;
  r:ДОСТУП К Вект.Вид;
  label1:КЛЮЧ;
УКАЗ
  посл1:=РАЗМЕР(A,0)-1;
  посл2:=РАЗМЕР(A,1)-1;
  g:=0;
  Scale:=0;
  Anorm:=0;
  СОЗДАТЬ(r,посл2+1);
  (* приведение к бидиагональному виду методом Хаусхолдера *)
  ОТ i:=0 ДО посл2 ВЫП
    l:=i+1;
    r[i]:=Scale*g;
    g:=0;
    t:=0;
    Scale:=0;
    ЕСЛИ i <= посл1 ТО
      ОТ k:=i ДО посл1 ВЫП
        Scale:=Scale+МОДУЛЬ(A[k,i]) 
      КОН;
      ЕСЛИ Scale # 0 ТО
        ОТ k:=i ДО посл1 ВЫП
          A[k,i]:=A[k,i]/Scale;
          t:=t+Матем.кв(A[k,i])
        КОН;
        f:=A[i,i];
        g:=-Матем.знак(f)*Матем.квкор(t);
        h:=f*g-t;
        A[i,i]:=f-g;
        ЕСЛИ i # посл2 ТО
          ОТ j:=l ДО посл2 ВЫП
            t:=0;
            ОТ k:=i ДО посл1 ВЫП
              t:=t+A[k,i]*A[k,j]
            КОН;
            f:=t/h;
            ОТ k:=i ДО посл1 ВЫП
              A[k,j]:=A[k,j]+f*A[k,i]
            КОН
          КОН
        КОН;
        ОТ k:=i ДО посл1 ВЫП
          A[k,i]:=Scale*A[k,i]
        КОН
      КОН
    КОН;
    s[i]:=Scale*g;
    g:=0;
    t:=0;
    Scale:=0;
    ЕСЛИ (i <= посл1) И (i # посл2) ТО
      ОТ k:=l ДО посл2 ВЫП
        Scale:=Scale+МОДУЛЬ(A[i,k]) 
      КОН;
      ЕСЛИ Scale # 0 ТО
        ОТ k:=l ДО посл2 ВЫП
          A[i,k]:=A[i,k]/Scale;
          t:=t+Матем.кв(A[i,k])
        КОН;
        f:=A[i,l];
        g:=-Матем.знак(f)*Матем.квкор(t);
        h:=f*g-t;
        A[i,l]:=f-g;
        ОТ k:=l ДО посл2 ВЫП
          r[k]:=A[i,k]/h 
        КОН;
        ЕСЛИ i # посл1 ТО
          ОТ j:=l ДО посл1 ВЫП
            t:=0;
            ОТ k:=l ДО посл2 ВЫП
              t:=t+A[j,k]*A[i,k]
            КОН;
            ОТ k:=l ДО посл2 ВЫП
              A[j,k]:=A[j,k]+t*r[k]
            КОН;
          КОН 
        КОН;
        ОТ k:=l ДО посл2 ВЫП
          A[i,k]:=Scale*A[i,k]
        КОН
      КОН
    КОН;
    Anorm:=Матем.макс(Anorm,МОДУЛЬ(s[i])+МОДУЛЬ(r[i]));
  КОН;
  (* накопление правых преобразований *)
  ОТ i:=посл2 ДО 0 ПО -1 ВЫП
    ЕСЛИ i < посл2 ТО
      ЕСЛИ g # 0 ТО
        ОТ j:=l ДО посл2 ВЫП
          (* двойное деление предохраняет от возможной потери точности *)
          V[j,i]:=(A[i,j]/A[i,l])/g 
        КОН;
        ОТ j:=l ДО посл2 ВЫП
          t:=0;
          ОТ k:=l ДО посл2 ВЫП
            t:=t+A[i,k]*V[k,j]
          КОН;
          ОТ k:=l ДО посл2 ВЫП
            V[k,j]:=V[k,j]+t*V[k,i]
          КОН
        КОН
      КОН;
      ОТ j:=l ДО посл2 ВЫП
        V[i,j]:=0;
        V[j,i]:=0
      КОН
    КОН;
    V[i,i]:=1;
    g:=r[i];
    l:=i
  КОН;
  (* накопление левых преобразований *)
  ОТ i:=посл2 ДО 0 ПО -1 ВЫП
    l:=i+1;
    g:=s[i];
    ЕСЛИ i < посл2 ТО
      ОТ j:=l ДО посл2 ВЫП
        A[i,j]:=0 
      КОН 
    КОН;
    ЕСЛИ g # 0 ТО
      ЕСЛИ i # посл2 ТО
        ОТ j:=l ДО посл2 ВЫП
          t:=0;
          ОТ k:=l ДО посл1 ВЫП
            t:=t+A[k,i]*A[k,j]
          КОН;
          (* двойное деление предохраняет от возможной потери точности *)
          f:=(t/A[i,i])/g;
          ОТ k:=i ДО посл1 ВЫП
            A[k,j]:=A[k,j]+f*A[k,i]
          КОН;
        КОН 
      КОН;
      ОТ j:=i ДО посл1 ВЫП
        A[j,i]:=A[j,i]/g 
      КОН;
    ИНАЧЕ
      ОТ j:=i ДО посл1 ВЫП
        A[j,i]:=0 
      КОН 
    КОН;
    A[i,i]:=A[i,i]+1
  КОН;
  (* диагонализация бидиагональной формы *)
  ОТ k:=посл2 ДО 0 ПО -1 ВЫП
    Its:=0;
    КОЛЬЦО
      l:=k;
      (* проверка на расщепление *)
      КОЛЬЦО
        ЕСЛИ l < 0 ТО
          label1:=ВКЛ;
          ВЫХОД
        КОН;
        n:=l-1;
        ЕСЛИ (МОДУЛЬ(r[l])+Anorm) = Anorm ТО 
          label1:=ОТКЛ; 
          ВЫХОД
        КОН;
        (* r[0] всегда =0, поэтому s[-1] никогда не будет вычисляться *)
        ЕСЛИ (МОДУЛЬ(s[n])+Anorm) = Anorm ТО 
          label1:=ВКЛ;
          ВЫХОД
        КОН;
        УМЕНЬШИТЬ(l)
      КОН; (* кольцо *)
      ЕСЛИ label1 ТО 
        c:=0;
        t:=1;
        i:=l; 
        КОЛЬЦО
          ЕСЛИ i > k ТО
            ВЫХОД
          КОН;
          f:=t*r[i];
          r[i]:=c*r[i];
          ЕСЛИ (МОДУЛЬ(f)+Anorm) = Anorm ТО
            ВЫХОД
          КОН;
          g:=s[i];
          h:=Матем.Пифагор(f,g);
          s[i]:=h;
          c:=g/h;
          t:=-f/h;
          ОТ j:=0 ДО посл1 ВЫП
            y:=A[j,n];
            z:=A[j,i];
            A[j,n]:=y*c+z*t;
            A[j,i]:=-y*t+z*c
          КОН;
          УВЕЛИЧИТЬ(i)
        КОН (* кольцо *)
      КОН;
      (* проверка сходимости *)
      z:=s[k];
      ЕСЛИ l = k ТО
        ЕСЛИ z < 0 ТО
          (* сделаем s[k] неотрицательным *)
          s[k]:=-z;
          ОТ j:=0 ДО посл2 ВЫП
            V[j,k]:=-V[j,k]
          КОН
        КОН;
        (* сходимость *)
        ВЫХОД
      КОН;
      ЕСЛИ Its = 30 ТО
        ВОЗВРАТ НЕТ_СХОДИМОСТИ
      КОН;
      УВЕЛИЧИТЬ(Its);
      (* сдвиг снизу на минор 2 х 2 *)
      x:=s[l];
      n:=k-1;
      y:=s[n];
      g:=r[n];
      h:=r[k];
      f:=0.5*(((g+z)/h)*((g-z)/y)+y/h-h/y);
      g:=Матем.Пифагор(f,1);
      f:=x-(z/x)*z+(h/x)*(y/(f+Матем.знак(f)*МОДУЛЬ(g))-h);
      (* следующее QR преобразование *)
      c:=1;
      t:=1;
      ОТ i1:=l ДО n ВЫП
        i:=i1+1;
        g:=r[i];
        y:=s[i];
        h:=t*g;
        g:=c*g;
        z:=Матем.Пифагор(f,h);
        r[i1]:=z;
        c:=f/z;
        t:=h/z;
        f:=x*c+g*t;
        g:=-x*t+g*c;
        h:=y*t;
        y:=y*c;
        ОТ j:=0 ДО посл2 ВЫП
          x:=V[j,i1];
          z:=V[j,i];
          V[j,i1]:=x*c+z*t;
          V[j,i]:=-x*t+z*c
        КОН;
        z:=Матем.Пифагор(f,h);
        s[i1]:=z;
        (* вращение может быть произвольным при z=0 *)
        ЕСЛИ z # 0 ТО
          c:=f/z;
          t:=h/z
        КОН;
        f:=c*g+t*y;
        x:=-t*g+c*y;
        ОТ j:=0 ДО посл1 ВЫП
          y:=A[j,i1];
          z:=A[j,i];
          A[j,i1]:=y*c+z*t;
          A[j,i]:=-y*t+z*c
        КОН 
      КОН;
      r[l]:=0;
      r[k]:=f;
      s[k]:=x
    КОН (* кольцо *)
  КОН;
  ВОЗВРАТ 0
КОН РазложитьНаSV;

(******************************************************************************)
ЗАДАЧА ОбнулитьS-(s+:Вект.Вид; откл:Вещ);
(* Цель:  обнуляет наименьшие собственные значения по заданной границе
 ******************************************************************************
 * До:    < s >    - вектор собственных значений S
 *        <откл>   - относительное отклонение (граница будет равна откл*макс(S) )
 * После: < s >    - измененный вектор собственных значений *)
ПЕР
  граница:Вещ;
  i:ЦЕЛ;
УКАЗ
  граница:=откл*Вект.макс(s);
  ОТ i:=0 ДО РАЗМЕР(s)-1 ВЫП
    ЕСЛИ s[i] < граница ТО 
      s[i]:=0 
    КОН 
  КОН
КОН ОбнулитьS;

(******************************************************************************)
ЗАДАЧА РешитьИзSV-(U-:Вид; s-:Вект.Вид; V-:Вид; b-,x+:Вект.Вид);
(* Цель:  решение системы уравнений после преобразования исходной матрицы
 *        с помощью РазложитьНаSV и обнуления наименьших собственных значений
 *        с помощью ОбнулитьS
 ******************************************************************************
 * До:    < U > - матрица U после РазложитьНаSV
 *        < s > - вектор  S после РазложитьНаSV
 *        < V > - матрица V после РазложитьНаSV
 *        < b > - вектор свободных членов
 * После: < x > - вектор решения (V*Diag(1/S(i))*U'*b, для S(i) # 0) *)
ПЕР
  i,j,посл1,посл2:ЦЕЛ;
  сумма:Вещ;
  врем:ДОСТУП К Вект.Вид;
УКАЗ
  посл1:=РАЗМЕР(U,0)-1;
  посл2:=РАЗМЕР(U,1)-1;
  СОЗДАТЬ(врем,посл2+1);
  ОТ j:=0 ДО посл2 ВЫП
    сумма:=0;
    ЕСЛИ s[j] > 0 ТО
      ОТ i:=0 ДО посл1 ВЫП
        сумма:=сумма+U[i,j]*b[i]
      КОН;
      сумма:=сумма/s[j]
    КОН;
    врем[j]:=сумма
  КОН;
  ОТ j:=0 ДО посл2 ВЫП
    сумма:=0;
    ОТ i:=0 ДО посл2 ВЫП
      сумма:=сумма+V[j,i]*врем[i]
    КОН;
    x[j]:=сумма
  КОН;
КОН РешитьИзSV;

(******************************************************************************)
ЗАДАЧА ВосстановитьИзSV-(U-:Вид; s-:Вект.Вид; V-,A+:Вид);
(* Цель:  восстанавливает матрицу A перемножая U, S и V' после
 *        обнуления наименьших собственных значений задачей ОбнулитьS 
 ******************************************************************************
 * До:    < U > - матрица U после РазложитьНаSV
 *        < s > - вектор  S после РазложитьНаSV
 *        < V > - матрица V после РазложитьНаSV
 * После: < A > - восстановленная матрица *)
ПЕР
  i,j,k,посл1,посл2:ЦЕЛ;
УКАЗ
  посл1:=РАЗМЕР(U,0)-1;
  посл2:=РАЗМЕР(U,1)-1;
  ОТ i:=0 ДО посл1 ВЫП
    ОТ j:=0 ДО посл2 ВЫП
      A[i,j]:=0;
      ОТ k:=0 ДО посл2 ВЫП
        ЕСЛИ s[k] > 0 ТО
          A[i,j]:=A[i,j]+U[i,k]*V[j,k]
        КОН 
      КОН
    КОН 
  КОН
КОН ВосстановитьИзSV;

(******************************************************************************)
ЗАДАЧА РазложитьНаQR-(A+,R+:Вид):ЦЕЛ;
(* Цель:  QR разложение прямоугольной матрицы  (N x M, с N >= M) на два
 *        сомножителя (A=Q*R), где Q (N x M) ортогональная матрица, а
 *        R (M x M) - верхняя треугольная матрица. Эта задача используется
 *        совместно с РешитьИзQR для решения систем уравнений.
 ******************************************************************************
 * До:    < A > - исходная матрица
 * После: < A > - содержит элементы Q
 *        < R > - верхняя треугольная матрица
 * Ответ: 0 или ВЫРОЖДЕНА *)
ПЕР
  i,j,k,посл1,посл2:ЦЕЛ;
  сумма:Вещ;
УКАЗ
  посл1:=РАЗМЕР(A,0)-1;
  посл2:=РАЗМЕР(A,1)-1;
  ОТ k:=0 ДО посл2 ВЫП
    (* вычисляем k-й диагональный элемент  *)
    сумма:=0;
    ОТ i:=0 ДО посл1 ВЫП
      сумма:=сумма+Матем.кв(A[i,k]) 
    КОН;

    ЕСЛИ сумма = 0 ТО
      ВОЗВРАТ ВЫРОЖДЕНА
    КОН;

    R[k,k]:=Матем.квкор(сумма);

    (* делим k-й столбец < A > на k-й диагональный элемент 
     * (это начало перезаписи < A > на < q >) *)
    ОТ i:=0 ДО посл1 ВЫП
      A[i,k]:=A[i,k]/R[k,k]
    КОН;

    ОТ j:=(k+1) ДО посл2 ВЫП
      (* дополняем оставшиеся элементы в столбце  *)
      сумма:=0;
      ОТ i:=0 ДО посл1 ВЫП
        сумма:=сумма+A[i,k]*A[i,j]
      КОН;
      R[k,j]:=сумма;

      (* обновляем элементы столбца матрицы < q > (< A >) *)
      ОТ i:=0 ДО посл1 ВЫП
        A[i,j]:=A[i,j]-A[i,k]*R[k,j]
      КОН
    КОН
  КОН;

  ВОЗВРАТ 0;
КОН РазложитьНаQR;

(******************************************************************************)
ЗАДАЧА РешитьИзQR-(q-,R-:Вид; b-,x+:Вект.Вид);
(* Цель:  решение системы уравнений после преобразования исходной матрицы
 *        с помощью РазложитьНаQR
 ******************************************************************************
 * До:    < q > - матрица Q после РазложитьНаQR
 *        < R > - матрица R после РазложитьНаQR
 *        < b > - вектор свободных членов
 * После: < x > - вектор решения *)
ПЕР
  i,j,посл1,посл2:ЦЕЛ;
  сумма:Вещ;
УКАЗ
  посл1:=РАЗМЕР(q,0)-1;
  посл2:=РАЗМЕР(q,1)-1;
                     (* строим q'b и записываем результат в x *)
  ОТ j:=0 ДО посл2 ВЫП
    x[j]:=0;
    ОТ i:=0 ДО посл1 ВЫП
      x[j]:=x[j]+q[i,j]*b[i]
    КОН
  КОН;
                              (* обновляем  вектором решения *)
  x[посл2]:=x[посл2]/R[посл2,посл2];
  ОТ i:=(посл2-1) ДО 0 ПО -1 ВЫП
    сумма:=0;
    ОТ j:=(i+1) ДО посл2 ВЫП
      сумма:=сумма+R[i,j]*x[j]
    КОН;
    x[i]:=(x[i]-сумма)/R[i,i]
  КОН
КОН РешитьИзQR;

КОН Матр.

 
 


Вопросы, замечания и предложения высылайте на atimopheyev@yahoo.com

 
Главная     ◄Глагол     ◄Азбука     ◄Задачи на Глаголе     Примеры приложений ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы